package report1.bank;

import java.util.HashMap;
import java.util.List;
import java.util.Scanner;

/**
 * Author：zouran
 * Date：2023/4/6  15:17
 * Description:
 */
public class Calculate {
    //最大行数
    private static final int max_size = 5;
    //无效参数，没啥用
    private static final int max_resourceCount = 3;
    //记录系统进程资源数目
    private final List<HashMap<String, Resource>> hashMapList = new java.util.ArrayList<>();
    //用户请求资源集合
    private final Integer[] request = new Integer[max_resourceCount];
    //安全序列全排列工具
    private final Integer[] safe_list_util = new Integer[max_size];
    private final Integer[][] initializeList = {
            {7, 5, 3, 0, 1, 0},
            {3, 2, 2, 2, 0, 0},
            {9, 0, 2, 3, 0, 2},
            {2, 2, 2, 2, 1, 1},
            {4, 3, 3, 0, 0, 2}
    };
    //安全数列
    private Integer[] safe_list = new Integer[max_size];
    //记录是否存在安全序列
    private boolean flag = false;
    //初始化可用资源
    private Resource available = new Resource(3, 3, 2);

    //初始化进程信息
    public void initialize() {
        for (int i = 0; i < max_size; i++) {
            safe_list_util[i] = i;
        }
//        HashMap<String,Resource> hashMap=new HashMap<>();
        for (Integer[] Integers : initializeList) {
            HashMap<String, Resource> hashMap = new HashMap<>();
            Resource allocation = new Resource(Integers[3], Integers[4], Integers[5]);
            Resource need = new Resource(Integers[0] - Integers[3], Integers[1] - Integers[4], Integers[2] - Integers[5]);
            hashMap.put("allocation", allocation);
            hashMap.put("need", need);
            hashMapList.add(hashMap);
        }
    }

    //获取输入
    public void input() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入需要申请资源的进程号（0-4）:");
        //记录用户请求的进程号
        int index = scanner.nextInt();
        if (index == -1) System.exit(0);
        Resource indexNeed = hashMapList.get(index).get("need");
        Resource indexAllocation = hashMapList.get(index).get("allocation");
        int ANeed = indexNeed.getA();
        int BNeed = indexNeed.getB();
        int CNeed = indexNeed.getC();
        System.out.println("请输入需要申请的资源数(空格为间隔符):");
        for (int i = 0; i < max_resourceCount; i++) {
            request[i] = scanner.nextInt();
        }
        //request<=need
        if (request[0] <= ANeed && request[1] <= BNeed && request[2] <= CNeed) {
            //request<=available
            if (request[0] <= available.getA() && request[1] <= available.getB() && request[2] <= available.getC()) {
                //数据备份，当不够分配时使用
                Resource available0 = new Resource(available);
                Resource indexNeed0 = new Resource(indexNeed);
                Resource indexAllocation0 = new Resource(indexAllocation);
                //成功请求、更新available、请求资源的need、allocation
                available = new Resource(available.getA() - request[0], available.getB() - request[1], available.getC() - request[2]);
                indexNeed = new Resource(indexNeed.getA() - request[0], indexNeed.getB() - request[1], indexNeed.getC() - request[2]);
                indexAllocation = new Resource(indexAllocation.getA() + request[0], indexAllocation.getB() + request[1], indexAllocation.getC() + request[2]);
                hashMapList.get(index).replace("need", indexNeed);
                hashMapList.get(index).replace("allocation", indexAllocation);
//              //查找安全序列
                search_safe_list(0, max_size, safe_list_util);
                //找到则打印安全序列
                if (flag) {
                    print_safe_list(safe_list);
                    safe_list = null;
                } else {
                    System.out.println("未找到安全序列，继续分配将导致系统进入不安全状态，进而可能引发死锁，不予分配资源！！");
                    //返回原有状态
                    available = new Resource(available0);
                    indexAllocation = new Resource(indexAllocation0);
                    indexNeed = new Resource(indexNeed0);
                    hashMapList.get(index).replace("need", indexNeed);
                    hashMapList.get(index).replace("allocation", indexAllocation);
                }
            } else System.out.println("您的要求超出了需要范围，导致BLOCK，请重新输入！");
        } else System.out.println("您的要求超出了需要范围，导致ERROR，请重新输入！");
        //将flag=false,否则下次请求必有安全序列
        flag = false;
        input();
    }

    //全排列寻找安全序列
    public void search_safe_list(Integer begin, Integer end, Integer[] integer) {
        //若已找到，则结束递归
        if (flag) return;
        if (begin + 1 == end) {
            if (judge_safe_list(integer)) {
                //safe_list=integer会导致safe_list与integer值一致
                System.arraycopy(integer, 0, safe_list, 0, integer.length);
                //标记存在安全序列
                flag = true;
            }
            return;
        }
        //递归全排列
        for (Integer i = begin; i < end; i++) {
            Integer temp = integer[begin];
            integer[begin] = integer[i];
            integer[i] = temp;
            search_safe_list(begin + 1, end, integer);
            temp = integer[begin];
            integer[begin] = integer[i];
            integer[i] = temp;
        }
    }

    //检验当前安全序列是否合格
    public boolean judge_safe_list(Integer[] integer) {
        Resource work = new Resource(available.getA(), available.getB(), available.getC());
        for (Integer integer1 : integer) {
            //need<work?
            if (hashMapList.get(integer1).get("need").getA() <= work.getA()
                    && hashMapList.get(integer1).get("need").getB() <= work.getB()
                    && hashMapList.get(integer1).get("need").getC() <= work.getC()) {
                work.setA(hashMapList.get(integer1).get("allocation").getA() + work.getA());
                work.setB(hashMapList.get(integer1).get("allocation").getB() + work.getB());
                work.setC(hashMapList.get(integer1).get("allocation").getC() + work.getC());
            } else {
                return false;
            }
        }
        return true;
    }

    //打印安全序列
    public void print_safe_list(Integer[] integer) {
        System.out.printf("%s\t%s\t%s\t%s\t%s\t%s\n", "进程号", "WORK", "NEED", "ALLO", "WORK+ALLO", "FINISH");
        Resource currentResource = new Resource(available.getA(), available.getB(), available.getC());
        for (Integer integer1 : integer) {
            Resource work = currentResource;
            Resource allocation = hashMapList.get(integer1).get("allocation");
            Resource need = hashMapList.get(integer1).get("need");
            //同currentResource.set方法
            currentResource = new Resource(work.getA() + allocation.getA(), work.getB() + allocation.getB(), work.getC() + allocation.getC());
            System.out.printf("%s\t%s\t%s\t%s\t%s\t%s\n", integer1, work.print(), need.print(), allocation.print(), currentResource.print(), "true");
        }
        System.out.println("时刻安全，存在安全序列: p" + safe_list[0] + ">p" + safe_list[1] + ">p" + safe_list[2] + ">p" + safe_list[3] + ">p" + safe_list[4]);
    }

    public void exe() {
        initialize();
        //一开始检验安全序列
        System.out.println("T0时刻安全性检测中。。。");
        search_safe_list(0, max_size, safe_list_util);
        if (flag) {
            print_safe_list(safe_list);
        }
        flag = false;
        input();
    }
}
